﻿#region << 文件说明 >>

/*----------------------------------------------------------------
 * 命名空间：Vampirewal.BlogCore
 * 唯一标识：d7b88953-f206-4fff-87d0-cbe3fff9b04e
 * 文件名：test
 *
 * 创建者：杨程
 * 电子邮箱：235160615@qq.com
 * 创建时间：2024/6/12 9:23:39
 * 版本：V1.0.0
 * 描述：
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/

#endregion << 文件说明 >>

global using Microsoft.AspNetCore.Builder;
global using Microsoft.Extensions.DependencyInjection;
global using System;
global using System.Collections.Generic;
global using System.ComponentModel;
global using System.Linq;
global using System.Reflection;
global using System.Text;
global using System.Threading.Tasks;
global using Microsoft.AspNetCore.Http;
global using Microsoft.AspNetCore.Mvc;
global using System.ComponentModel.DataAnnotations;
global using Microsoft.AspNetCore.Routing;
global using System.Text.Json;
global using System.Text.Json.Serialization;
global using Microsoft.Extensions.Options;
global using Microsoft.Extensions.Configuration;

namespace Vampirewal.BlogCore;

/// <summary>
/// 全局APP静态类
/// </summary>
public static partial class App
{
    static App()
    {
        EffectiveTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).ToList();

        var configurationBuilder= new ConfigurationBuilder().SetBasePath($"{AppDomain.CurrentDomain.BaseDirectory}Configuration");

        var jsonFiles= Directory.EnumerateFiles($"{AppDomain.CurrentDomain.BaseDirectory}Configuration");
        foreach (var path in jsonFiles)
        {
            configurationBuilder.AddJsonFile(path);
        }

        Configuration = configurationBuilder.Build();
    }

    /// <summary>
    /// 有效程序集类型
    /// </summary>
    public static readonly List<Type> EffectiveTypes;

    /// <summary>
    /// 根路径
    /// </summary>
    public static readonly string RootPath = $"{AppDomain.CurrentDomain.BaseDirectory}wwwroot";

    /// <summary>
    /// IOC容器
    /// </summary>
    public static IServiceProvider Service { get; internal set; }

    /// <summary>
    /// 全局配置选项
    /// </summary>
    public static IConfiguration Configuration { get; internal set; }

    public static TOptions GetConfig<TOptions>(string path)
    {
        TOptions val = Configuration.GetSection(path).Get<TOptions>();
        
        return val;
    }

    public static TOptions GetOption<TOptions>(this IServiceProvider service)
    {
        var path= nameof(TOptions).Replace("Options", "");

        return GetConfig<TOptions>(path);
    }

    /// <summary>
    /// 配置
    /// </summary>
    private static BlogCoreConfig _Config { get; set; }

    /// <summary>
    /// 是否启动了
    /// </summary>
    private static bool IsRun { get; set; } = false;

    /// <summary>
    /// 启动程序
    /// </summary>
    /// <param name="args">启动参数</param>
    /// <param name="html">html页面配置</param>
    /// <param name="configService">配置IOC容器</param>
    /// <param name="app">配置中间件</param>
    /// <param name="endpoint">配置MiniApi接口</param>
    /// <param name="onBeforeLoad">html页面加载前</param>
    /// <param name="onAfterLoaded">html页面加载后</param>
    /// <param name="loginAuthCheck">html配置中设置了权限验证之后，这里需要实现</param>
    /// <exception cref="Exception"></exception>
    public static void RunBlog(string[] args,
                               Action<HtmlConfig> html, 
                               Action<IServiceCollection>? configService = null,
                               Action<WebApplication>? app = null, 
                               Action<IEndpointRouteBuilder>? endpoint = null, 
                               Action<HttpRequest>? onBeforeLoad = null, 
                               Action<HttpRequest, string>? onAfterLoaded = null,
                               Func<string,string,bool>? loginAuthCheck=null)
    {
        if (!IsRun)
        {
            _Config = new BlogCoreConfig();

            _Config._builder = WebApplication.CreateBuilder(args);

            if (!Directory.Exists(App.RootPath))
            {
                Directory.CreateDirectory(App.RootPath);
            }

            //_Config.RegisterOptions();

            _Config._builder.Services.AddBlogOptions<BlogOptions>();

            configService?.Invoke(_Config._builder.Services);

            _Config._builder.Services.AddHttpContextAccessor();

            _Config._webApplication = _Config._builder.Build();

            VampirewalMessenger.GetInstance().RegistAll(_Config._webApplication.Services);

            Service = _Config._webApplication.Services;

            _Config._htmlConfig = new HtmlConfig();

            _Config.Configure(app);

            _Config.UseEndpoints(endpoint);

            _Config.ConfigureHtmlCongfig(html);

            _onBeforeLoad = onBeforeLoad;
            _onAfterLoaded = onAfterLoaded;
            _OnAuthCheck = loginAuthCheck;

            _Config.OnHtmlBeforeLoad += Config_OnHtmlBeforeLoad;
            _Config.OnHtmlAfterLoaded += Config_OnHtmlAfterLoaded;

            if (_Config._htmlConfig.LoginAuthCheck)
            {
                if (loginAuthCheck == null)
                    throw new ArgumentNullException("页面配置了鉴权，这里的委托不能为空！");

                _Config.OnLoginAuth += _Config_OnLoginAuth;
            }
                

            if (!_Config.IsEditHtml)
                throw new Exception("未配置Html信息！");

            _Config._webApplication.Run();

            IsRun = true;
        }
        else
        {
            throw new Exception("程序已经启动，请勿重复操作!");
        }
    }

    

    private static Action<HttpRequest>? _onBeforeLoad { get; set; }

    private static void Config_OnHtmlBeforeLoad(HttpRequest request)
    {
        _onBeforeLoad?.Invoke(request);
    }

    private static Action<HttpRequest, string>? _onAfterLoaded { get; set; }

    private static void Config_OnHtmlAfterLoaded(HttpRequest request, string html)
    {
        _onAfterLoaded?.Invoke(request, html);
    }

    private static Func<string,string,bool> _OnAuthCheck { get; set; }
    private static bool _Config_OnLoginAuth(string username, string password)
    {
        if(_OnAuthCheck!=null)
            return _OnAuthCheck.Invoke(username, password);

        return true;

    }
    /// <summary>
    /// 生成ID
    /// </summary>
    /// <returns></returns>
    public static string GenerateId()
    {
        return Guid.NewGuid().ToString().Replace("-", "").Substring(0, 5);
    }

    /// <summary>
    /// 获取枚举的描述特性
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public static string? GetDescription(this Enum value)
    {
        return value.GetType()
                    ?.GetMember(value.ToString() ?? string.Empty)
                    ?.FirstOrDefault()
                    ?.GetCustomAttribute<DescriptionAttribute>()
                    ?.Description;
    }

    /// <summary>
    /// 生成顶部提示消息Html
    /// </summary>
    /// <param name="message"></param>
    /// <param name="type"></param>
    /// <returns></returns>
    public static string Message(string message, string type = "success")
    {
        return $"this.$message({{ message: '{message}',type: '{type}'}})";
    }

    /// <summary>
    /// 获取服务地址
    /// </summary>
    /// <returns></returns>
    public static string GetLocalhost(HttpRequest request)
    {
        string result = $"{request.HttpContext.Request.Scheme}://{request.HttpContext.Request.Host.Value}";

        // 代理模式：获取真正的本机地址
        // X-Original-Host=原始请求
        // X-Forwarded-Server=从哪里转发过来
        if (request.HttpContext.Request.Headers.ContainsKey("Origin")) // 配置成完整的路径如（结尾不要带"/"）,比如 https://www.abc.com
            result = $"{request.HttpContext.Request.Headers["Origin"]}";
        else if (request.HttpContext.Request.Headers.ContainsKey("X-Original")) // 配置成完整的路径如（结尾不要带"/"）,比如 https://www.abc.com
            result = $"{request.HttpContext.Request.Headers["X-Original"]}";
        else if (request.HttpContext.Request.Headers.ContainsKey("X-Original-Host"))
            result = $"{request.HttpContext.Request.Scheme}://{request.HttpContext.Request.Headers["X-Original-Host"]}";
        return result;
    }

    /// <summary>
    /// 将控件插入父控件的集合中
    /// </summary>
    /// <param name="control"></param>
    /// <param name="list"></param>
    public static void AddToChildren(this ControlBase control, List<ControlBase> list)
    {
        list.Add(control);
    }

    /// <summary>
    /// 将控件插入父控件的集合中
    /// </summary>
    /// <param name="list"></param>
    /// <param name="control"></param>
    public static void AddToChildren(this List<ControlBase> list, ControlBase control)
    {
        list.Add(control);
    }

    /// <summary>
    /// json序列化配置
    /// </summary>
    internal static JsonSerializerOptions JsonOptions { get; set; }

    /// <summary>
    /// 设置json序列化配置
    /// </summary>
    /// <param name="options"></param>
    public static void SetJsonOptions(Func<JsonSerializerOptions>? options)
    {
        var op = options?.Invoke();
        if (op != null)
            JsonOptions = op;
        else
            JsonOptions = new JsonSerializerOptions
            {
                WriteIndented = true, // 使 JSON 输出格式化
                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, // 忽略 null 值
                Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
            };
    }

    /// <summary>
    /// json序列化
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static string JsonSerialize(object obj)
    {
        if (JsonOptions == null)
        {
            SetJsonOptions(null);
        }

        return JsonSerializer.Serialize(obj, JsonOptions);
    }

    /// <summary>
    /// 表格数据字典
    /// </summary>
    internal static Dictionary<string, object> TableDataDic { get; set; } = new Dictionary<string, object>();
}